import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
from PyQt5.QtCore import pyqtSlot, QThread, pyqtSignal
from need.ping_v2 import Ui_pingWindow
import threading
import subprocess
import time
from queue import Queue
import platform
# import tempfile

# 定义sucess列表、工作进程数和初始化队列
ipSuccess = []
Work_Thread = 254
ipQueue = Queue()

# 初始化主窗口类


class pingWindow(QMainWindow, Ui_pingWindow):
    def __init__(self, parent=None):
        super(pingWindow, self).__init__(parent)
        self.setupUi(self)
        # 初始化多线程对象
        self.thread = Work_QThread()
        # 按钮点击后传给work函数
        self.ping.clicked.connect(self.work)
        # 接收到信号后传递给goStop函数
        self.thread.trigger.connect(self.goStop)
        # 初始化状态栏信息
        self.statusbar.showMessage("请按照提示信息操作...")

    # 执行前清除上一次显示结果
    def clear_color(self):
        # 清除旧颜色，默认颜色为灰色，background-color: rgb(217, 217, 217) 灰色
        for i in range(1, 255):
            ui_default = 'ui.ip_' + \
                str(i) + '.setStyleSheet("background-color: rgb(217, 217, 217)")'
            # 使用eval执行字符串命令/赋值
            eval(ui_default)

    # 点击按钮后的操作
    def work(self):
        a = ui.ip_line.text()
        if len(a) > 0 and len(a.split('.')) == 4 and a.split('.')[-1] == '':
            # 调用清除颜色的函数
            self.clear_color()
            # 多线程调用/执行
            self.thread.start()
            # 任务执行时将ping按钮设置成不可用
            self.ping.setEnabled(False)

        else:
            QMessageBox.information(ui, "提示信息", "检测到输入信息不正确，请输入正确的IP网段信息。")

    # 多线程执行完毕后调用gostop函数
    def goStop(self):
        # 任务结束后恢复按钮可用
        self.ping.setEnabled(True)
        QMessageBox.information(ui, "提示信息", "操作已成功执行。")

    # 多线程ping主函数，注意不需要传入self函数

    def pingIp():
        # 消费队列里的IP地址
        while not ipQueue.empty():
            ip = ipQueue.get()
            # 跟cli一样，linux或macos注意修改为：ping -c 2 -W 5
            if (platform.system()) == "Windows":

                cmd = 'ping -n 2 -w 5 %s' % ip
            else:
                cmd = 'ping -c 2 -W 5 %s' % ip
            # 此处未使用管道，直接使用temp临时文件，加快处理速度
            # out_temp = tempfile.TemporaryFile(mode='w+')
            # fileno = out_temp.fileno()
            # p = subprocess.call(cmd, stdout=fileno, stderr=fileno)
            # 判断返回值是0（0代表命令成功执行）
            # if p == 0:
            # 成功返回0，将从队列中遍历的IP信息存入成功列表
            # ipSuccess.append(ip)

            if (platform.system()) == "Windows":
                # si = subprocess.STARTUPINFO()
                # si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
                # p = subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
                #                      stderr=subprocess.STDOUT, universal_newlines=True, startupinfo=si)
                # p.communicate()
                # if p.returncode == 0:
                #     ipSuccess.append(ip)

                DETACHED_PROCESS = 0x00000008
                p = subprocess.call(cmd, stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE, creationflags=DETACHED_PROCESS)
                if p == 0:
                    ipSuccess.append(ip)

            else:
                p = subprocess.call(cmd, stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE, shell=True)
                if p == 0:
                    ipSuccess.append(ip)

# 任务逻辑和主窗口进程拆分，防止出现未响应或程序执行时主界面假死


class Work_QThread(QThread):
    trigger = pyqtSignal()

    def __init__(self):
        super(Work_QThread, self).__init__()

    @pyqtSlot()  # 防止多次执行
    def run(self):

        start_time = time.time()
        ui.statusbar.showMessage("程序执行中...")
        a = ui.ip_line.text()
        for i in range(1, 255):
            ipQueue.put(a + str(i))

        # 获取网段信息并加入队列
        threads = []
        for i in range(Work_Thread):
            # 多线程调用pingIP主函数
            thread = threading.Thread(target=pingWindow.pingIp)
            thread.start()
            threads.append(thread)
        for thread in threads:
            thread.join()

        # 可以ping通的存入sucess列表
        for i in ipSuccess:
            ip_green = 'ip_' + str(i.split(a)[1])
            ui_info = 'ui.' + ip_green + \
                '.setStyleSheet("background-color:green")'  # 修改UI标签背景为绿色
            eval(ui_info)

        time_info = format(time.time() - start_time, '.2f')
        statusbar_info = '在线台数:' + \
            str(len(ipSuccess)) + ' '*5+'执行耗时:' + time_info + 's'

        # 显示状态栏信息
        ui.statusbar.showMessage(statusbar_info)
        # 清除列表，避免重复统计
        ipSuccess.clear()
        # 发送信号
        self.trigger.emit()


if __name__ == '__main__':
    # 初始化PyQt5窗口
    app = QApplication(sys.argv)
    ui = pingWindow()
    ui.show()
    sys.exit(app.exec_())
